(function(angular) {
	'use strict';
	angular.module("fs.waf").factory("userService", userService);
	userService.$inject = [ '$q', 'loggerFactory', 'commonService', 'ajaxServiceFactory', 'gridService','modalService', 'arithService','$filter' ];
	function userService($q, loggerFactory, commonService, ajaxServiceFactory, gridService, modalService, arithService, $filter) {
		var log = loggerFactory.getLogger("userService"), ajaxService = ajaxServiceFactory.buildAjaxService({
			getUserOptions : {
				url : 'do/cda/dataList/userOptions',
				method : 'get'
			},
			getLookupUserStatus : {
				url : 'do/cda/dataList/lookupUserStatus',
				method : 'post'
			}
		});
		function getLookupUserStatus(param){
			var defer = $q.defer();
			var user = param;
			ajaxService.getLookupUserStatus(user).then(function(response) {
				defer.resolve(response);
			});
			return defer.promise;
		}
		function initOptions(ctrl, userOptions) {
			ctrl.localeCodeOptions = userOptions.local;
			ctrl.addrCountryOptions = userOptions.country;
			ctrl.userStatusOptions = userOptions.userStatus;

		};
		
		function loadOptions() {
			var defer = $q.defer();
			ajaxService.getUserOptions().then(function(response) {
				var userOptions = {};
				if (response.data) {
					angular.forEach(response.data, function(value, key) {
						var tempValue = {};
						tempValue.data = value;
						userOptions[key] = tempValue;
					});
				}
				defer.resolve(userOptions);
			});
			return defer.promise;
		}
		
		return {
			initOptions : initOptions,
			initDynaParm : initDynaParm,
			initRole : initRole,
			initGroup : initGroup,
			initToken: initToken,
			getLookupUserStatus : getLookupUserStatus,
			loadOptions : loadOptions
		};
		
		function initRole($scope, ctrl) {
			//init role grid
			ctrl.roleGridOptions = gridService.createInnerGridOptions($scope, ctrl.layoutConfig.formConfigs.role.tableConfigs.table, rowSelectionRoleChanged);
			ctrl.roleGridOptions.data = 'vm.user.userRoles';
			ctrl.roleGridOptions.verifyData = 'vm.userOld.userRoles';
			function rowSelectionRoleChanged(eventRow, selectedRows) {
				ctrl.selectedRoles = selectedRows;
			}
			
			ctrl.addRole = function(row) {
			 return $q(function(resolved, rejected){
				var params = {"multiSelect": "true"};
				params.roleCodes = [];
				angular.forEach(ctrl.user.userRoles, function(role, index) {
					params.roleCodes.push(role.roleCode);
				});
				modalService.openCustomDialogs({
					'dialogsModule' : 'cda.role',
					'params' : params,
					'btnCallback' : {
						'ok' : function(selectedRows) {
							if (!selectedRows || selectedRows.length == 0) {
								modalService.openErrorDialogs({
									messages : [ 'title.dialogs.info.norecsel' ]
								});
								return false;
							}
							if (!ctrl.user.userRoles) {
								ctrl.user.userRoles = [];
							}
							angular.forEach(selectedRows, function(data, index, array){
								data.dataStatus = 'C';
								ctrl.user.userRoles.push(data);
							});
						},
						'close' : function(){
							rejected();
						}
					}
				});
			  });
			};
			
		}
		
		function initGroup($scope, ctrl) {
			//init group grid
			ctrl.groupGridOptions = gridService.createInnerGridOptions($scope, ctrl.layoutConfig.formConfigs.group.tableConfigs.table, rowSelectionGroupChanged);
			ctrl.groupGridOptions.data = 'vm.user.userGroups';
			ctrl.groupGridOptions.verifyData = 'vm.userOld.userGroups';
			function rowSelectionGroupChanged(eventRow, selectedRows) {
				ctrl.selectedGroups = selectedRows;
			}
			
			ctrl.addGroup = function(row) {
			  return $q(function(resolved, rejected){
				var params = {"multiSelect": "true"};
				params.groups = [];
				angular.forEach(ctrl.user.userGroups, function(group, index) {
					params.groups.push($filter('encode')(group.groupCode));
				});
				modalService.openCustomDialogs({
					'dialogsModule' : 'cda.group',
					'params' : params,
					'btnCallback' : {
						'ok' : function(selectedRows) {
							if (!selectedRows || selectedRows.length == 0) {
								modalService.openErrorDialogs({
									messages : [ 'title.dialogs.info.norecsel' ]
								});
								return false;
							}
							if (!ctrl.user.groups) {
								ctrl.user.groups = [];
							}
							angular.forEach(selectedRows, function(data, index, array){
								data.dataStatus = 'C';
								ctrl.user.userGroups.push(data);
							});
						},
						'close' : function(){
							rejected();
						}
					}
				});
			  });
			};
			
		}
		
		function initToken($scope, ctrl) {
			//init token grid
			//add sub data validator
			ctrl.validatorConfig=ctrl.validatorConfig ||{};
			if(ctrl.validatorConfig) ctrl.layoutConfig.formConfigs.token.tableConfigs.table.validatorConfig = ctrl.validatorConfig.userTokens;
			ctrl.tokenGridOptions = gridService.createInnerGridOptions($scope, ctrl.layoutConfig.formConfigs.token.tableConfigs.table, rowSelectionTokenChanged);
			ctrl.tokenGridOptions.data = 'vm.user.userTokens';
			ctrl.tokenGridOptions.verifyData = 'vm.userOld.userTokens';
			function rowSelectionTokenChanged(eventRow, selectedRows) {
				ctrl.selectedTokens = selectedRows;
			}
			
			ctrl.addAddr = function(row) {
				return $q(function(resolved, rejected){
					// params
					if(ctrl.user.userTokens.length<3){
						var params = {};
						params.tokenType="RSA";
						params.dataStatus = 'C';
						ctrl.user.userTokens.push(params);
					}else{
						modalService.openErrorDialogs({
							messages : [ 'js.info.user.token-own-only-three' ]
						});
						return;
					}
			   });
			};
		}
		
		function initDynaParm($scope, ctrl, updateProcessFlag) {
			
			if(ctrl.validatorConfig) ctrl.layoutConfig.formConfigs.userProfile.tableConfigs.tableSele.validatorConfig = ctrl.validatorConfig;
			ctrl.selectedPropertyInnerGridOptions = gridService.createInnerGridOptions($scope, ctrl.layoutConfig.formConfigs.userProfile.tableConfigs.tableSele, dynaParmSeleRowSelectionChanged);
			ctrl.selectedPropertyInnerGridOptions.data = 'vm.user.userProps';//dynamicParams
			ctrl.selectedPropertyInnerGridOptions.verifyData = 'vm.userOld.userProps';
			ctrl.selectedPropertyInnerGridOptions.multiSelect = true;
			function dynaParmSeleRowSelectionChanged(eventRow, selectedRows) {
				ctrl.selectedDynaParmSeleRows = selectedRows;
			}
			
			if (ctrl.layoutConfig.formConfigs.userProfile.tableConfigs.tableAvai) {
				ctrl.hasAvailablePropertyInnerGrid = 'Y';
				ctrl.availablePropertyInnerGridOptions = gridService.createInnerGridOptions($scope, ctrl.layoutConfig.formConfigs.userProfile.tableConfigs.tableAvai, dynaParmAvaiRowSelectionChanged);
				ctrl.availablePropertyInnerGridOptions.data = 'vm.availableProperties';
				ctrl.availablePropertyInnerGridOptions.multiSelect = true;
				function dynaParmAvaiRowSelectionChanged(eventRow, selectedRows) {
					ctrl.selectedDynaParmAvaiRows = selectedRows;
				}
			}
			
			ctrl.addUserProp = function(row){
				if (!ctrl.user.dynamicParams) {								
					ctrl.user.dynamicParams = {};
				}
				angular.forEach(ctrl.selectedDynaParmAvaiRows, function(selectedDynaParmAvai, key) {
					angular.forEach(ctrl.availableProperties, function(availableProperty, index) {
						if (availableProperty.$$hashKey == selectedDynaParmAvai.$$hashKey) {
							ctrl.availableProperties.splice(index, 1);
							// some new add not in site.dynamicParams, so need put it in
							if (!ctrl.user.dynamicParams[availableProperty.name] || !ctrl.user.dynamicParams[availableProperty.name].value) {
								ctrl.user.dynamicParams[availableProperty.name] = availableProperty;
								angular.merge(availableProperty, availableProperty.dynamicParameter);
							}
							// change 
							var corProf = angular.copy(availableProperty);
							corProf.dynamicParams = {};
							corProf.dynamicParams[availableProperty.name] = availableProperty;
							ctrl.user.userProps.push(corProf);
						}
					});
				});
				
				ctrl.selectedDynaParmAvaiRows = [];
				
			};

			ctrl.removeUserProp = function(){
				if (!ctrl.selectedDynaParmSeleRows || ctrl.selectedDynaParmSeleRows.length == 0) {
					modalService.openErrorDialogs({
						messages : [ 'title.dialogs.info.norecsel' ]
					});
					return false;
				}
				angular.forEach(ctrl.selectedDynaParmSeleRows, function(selectedParam, key) {
					angular.forEach(ctrl.user.userProps, function(userProp, index) {
						if (userProp.$$hashKey == selectedParam.$$hashKey) {
							// clear for delete, 
							delete ctrl.user.dynamicParams[userProp.name];
							
							ctrl.user.userProps.splice(index, 1);
							ctrl.availableProperties.push(userProp);
						}
					});
				});
				ctrl.selectedDynaParmSeleRows = [];
				
			};
			
			ctrl.resetDynaProperties = function () {
				resetSelectedProperties();
				resetAvailableProperties();
			};
			
			function resetSelectedProperties () {
				if (!ctrl.user.userProps) {								
					ctrl.user.userProps = [];
				}
				//ctrl.user.userProps
				var dynamicParams = ctrl.user.dynamicParams;
				if (dynamicParams) {
					angular.forEach(dynamicParams, function(dynamicParam, key) {
						// some new add prop or exist prop, then remove, also commit to server but value is empty, so need add '&& dynamicParam.value' to check
						if (dynamicParam.subCategory == 'USERPROFILE' && dynamicParam.value) {
							ctrl.user.userProps.push(dynamicParam);
						}
					});
				}
				
				if (ctrl.userOld) {
					if (!ctrl.userOld.userProps) {								
						ctrl.userOld.userProps = [];
					}
					//ctrl.user.userProps
					var oldDynamicParams = ctrl.userOld.dynamicParams;
					if (oldDynamicParams) {
						angular.forEach(oldDynamicParams, function(dynamicParam, key) {
							// some new add prop or exist prop, then remove, also commit to server but value is empty, so need add '&& dynamicParam.value' to check
							if (dynamicParam.category == 'USERPROFILE' && dynamicParam.value) {
								// change, build some dynaparm define
								var corProf = angular.copy(dynamicParam);
								// need dynamicParameter.name and dynamicParameter.dispKey
								corProf.dynamicParameter = angular.copy(dynamicParam);
								ctrl.userOld.userProps.push(corProf);
							}
						});
					}
				}
			}
			
			function resetAvailableProperties () {
				// change layoutConfig, get subCata 'CUSTOMERPROFILE'
				var custProfAvaiProps = [];
				var gridConfigs = ctrl.layoutConfig.formConfigs.userProfile.gridConfigs;
				if (gridConfigs) {
					angular.forEach(gridConfigs, function(gridConfig, key) {
						if (gridConfig.dynamicParameter && gridConfig.dynamicParameter.subCategory == 'USERPROFILE') {
							var dynaParm = angular.copy(gridConfig);
							var hasDyna = false;
							if (ctrl.user.userProps && ctrl.user.userProps.length > 0) {
								for (var i = 0; i < ctrl.user.userProps.length; i++) {
									var userProp = ctrl.user.userProps[i];
									if (userProp.name == dynaParm.dynamicParameter.name) {
										hasDyna = true;
										delete userProp.label;
										// change 
										var corProf = dynaParm;
										corProf.dynamicParams = {};
										corProf.dynamicParams[userProp.name] = userProp;
										// only for update verify
										corProf.primaryKey = userProp.primaryKey;
										corProf.value = userProp.value;
										ctrl.user.userProps[i] = corProf;
										break;
									}
								}
							}
							if (!hasDyna)
								custProfAvaiProps.push(dynaParm);
								//this will in tab cust Profile, not show other place
								gridConfig.show = false;
						}
					});
				}
				// some has value but not has layout dynaparm, need clear
				if (ctrl.user.userProps && ctrl.user.userProps.length > 0) {
					for (var i = ctrl.user.userProps.length - 1; i >= 0 ; i--) {
						var userProp = ctrl.user.userProps[i];
						if (!userProp.dynamicParams) {
							ctrl.user.userProps.splice(i, 1);
						}
					}
				}
				ctrl.availableProperties = custProfAvaiProps;
				
				sortDynamicParamters(ctrl.user.userProps);
				sortDynamicParamters(ctrl.availableProperties);
			};
			
			function sortDynamicParamters(serviceDymamicParamters){
				if(!serviceDymamicParamters){
					return;
				}
				serviceDymamicParamters.sort(function(p1, p2){
					return arithService.gt(p1.dynamicParameter.dispOrder, p2.dynamicParameter.dispOrder) ? 1 : -1;
				});
			}
			
		};
		
	}
})(angular);
